package cn.gz.lbs.main;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;

import org.apache.commons.configuration.CompositeConfiguration;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.impl.StdSchedulerFactory;

import test.HelloJob;

import com.netnewera.l1.ans.Ans;
import com.netnewera.l1.ans.Lcta;
import com.netnewera.l1.ans.Lia;
import com.netnewera.l1.ans.Lta;
import com.netnewera.l1.ans.Posinfo;
import com.netnewera.l1.report.Posinfos;
import com.netnewera.l1.req.Client;
import com.netnewera.l1.req.GeoInfo;
import com.netnewera.l1.req.Lctr;
import com.netnewera.l1.req.Lir;
import com.netnewera.l1.req.Ltr;
import com.netnewera.l1.req.Msids;
import com.netnewera.l1.req.Originator;
import com.netnewera.l1.req.PrTimer;
import com.netnewera.l1.req.Req;
import com.netnewera.l1.req.TimeRange;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder;

import cn.gz.lbs.entity.CmsUser;
import cn.gz.lbs.entity.LirNeedEntity;
import cn.gz.lbs.entity.TLbsHistory;
import cn.gz.lbs.glsc.GLSCProxy;
import cn.gz.lbs.jobs.CancelLTRJob;
import cn.gz.lbs.jobs.LtrrJob;
import cn.gz.lbs.servlet.LbsProxyServer;
import cn.gz.zoomtech.common.ConfManager;
import cn.gz.zoomtech.common.DateUtil;
import cn.gz.zoomtech.common.MessageUtil;
import cn.gz.zoomtech.common.db.DbHandle;

public class SPRequestManager {
	 private static final Log log = LogFactory.getLog(SPRequestManager.class);
	 private static CompositeConfiguration cf = ConfManager.getInstance().getConf();

	/**
	 * package_name: cn.gz.lbs.main
	 * file_name:    SPRequestManager.java
	 * description: 
	 * 2013-6-18下午4:24:17
	 * Author: chenhui
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}
	
	/**
	 * 
	* package_name: cn.gz.lbs.main
	* file_name:    SPRequestManager.java
	* description: 处理SP发送的定位请求(SP鉴权，定位请求类型分析，处理，记录，返回。)
	* 2013-7-8下午4:54:47
	* Author: chenhui
	 * @param req
	 * @param ip
	 * @return 定位处理结果XML字符串
	 */
	public String dealwithSpReq(String req,String ip){
		
		Long tranc_time_start = System.currentTimeMillis();
		
		String headStr = "<?xml version=\"1.0\"?><!DOCTYPE REQ SYSTEM \"LOCREQ.DTD\">";
		String headStr2 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE REQ SYSTEM \"LOCREQ.DTD\">";
		Ans ans = new Ans();
		String respHead = "<?xml version=\"1.0\"?><!DOCTYPE ANS SYSTEM \"LOCANS.DTD\">";
		String respStr = "defaultErrorWhenPhraseReq";
		String respMemo = "成功";

		XStream xStream = new XStream(new DomDriver("UTF-8", new XmlFriendlyNameCoder("-_", "_")));
		
		try{
			TLbsHistory entity = null;
			short respForm = 0;
			xStream.autodetectAnnotations(true);
			
			Date reqTime = new Date();			
			
//			step0_1:将请求字符串转换成请求REQ对象
			Req reqObject = new Req();
			String noHeadReq = req.replace(headStr, "");
			       noHeadReq = noHeadReq.replace(headStr2, ""); // update at 2013-08-29 18:00 because online logs
			
			log.info("noHeadReq is:"+noHeadReq);
			xStream.alias("REQ",Req.class);
			xStream.alias("CLIENT",Client.class);
			reqObject = (Req)xStream.fromXML(noHeadReq);
			
			String userName = null;
			String password = null;
			userName = reqObject.getClient().getLcsclientid();
			password = reqObject.getClient().getPassword();

//			step1:SP鉴权--IP，账号，密码
			boolean ipcheckOpen = cf.getBoolean("ipcheckOpen",false);
			int checkSp = 0; //默认鉴权成功
			String checkSPResult[] = checkSP(ip, userName, password);
			if(ipcheckOpen){
				if("true".equals(checkSPResult[0])){
					checkSp = 0;
				}else{
					checkSp = 1;
				}				 
			}
			
			log.info("ip:"+ip+",user:"+userName+",pwd:"+password+",checkSp:"+checkSp);
//			step1-1:SP鉴权成功
			if(checkSp==0){
				boolean isUnicomPhone = false; // 是否本省联通号码,否则禁止定位
//				step2:判断来访消息类型：            
				String reqType = this.checkReqType(req);
//				【case:LIR】step2_1: 当为LIR请求时的处理：
				if(reqType.equals("LIR")){
					ans = createDefaultSingleRespWithLia(reqObject);// 构建默认的返回ANS：
//					Lia lia = null;
//					boolean isSingleLir = false;
					String  tel = null;
					Lir lirOne = (Lir)reqObject.getLir();
//					step3: 判断：单用户立即定位，还是多用户立即定位以及 流控。
					List<String> msidList = lirOne.getMsids().getMsid();
//					step3-1:请求数据异常：请求中没有带需要定位的号码;
					if(msidList==null){
						ans.getLia().setResult("102"); // 被定位用户未知
						respStr = respHead+xStream.toXML(ans);
						log.info("reqIsLIRmsidListNUll102,resp:"+respStr);
						return respStr;

					}else{
//				   step:查询出关联的CMS用户信息
						DbHandle dbh = new DbHandle();
						CmsUser cmsUser =  dbh.queryCmsUserBySPipInfo(userName);
						log.info("requestCmsUser:"+cmsUser);
//						黑白名单开关由读配置文件改为读取单个SP的开关：
//						          表cms_user 新增字段：checkbw, 0:需要鉴权黑白名单；1:不需要，默认是0.
//						boolean blackWhiteOpen = cf.getBoolean("blackWhiteOpen", true); //黑白名单处理开关
						boolean blackWhiteOpen =  true;
						if(1==cmsUser.getCheckBw()){ // 不需要鉴权黑白名单
							blackWhiteOpen = false;
						}else{
							
						}
						int msidListSize = msidList.size();
						log.debug("msidListSize:"+msidListSize);
//				    step3-2:单用户立即定位请求
						if(msidListSize==1){
//							isSingleLir = true;
							tel = (String)msidList.get(0);
//							stepA: 流控检查
							
							if(cmsUser==null||cmsUser.getReq_count()>=cmsUser.getReq_max()){ // 流控检查不能通过
								
								ans.getLia().setResult("900"); // 900 : SP 请求达到流控最大值，拒绝定位请求.
								respStr = respHead+xStream.toXML(ans);
								log.info("reqIsLIRhadMax900,resp:"+respStr);
								return respStr;
							}else{// 流控检查通过，则继续：黑白名单处理,从缓存取定位结果，没有就从远程服务端GLSC（总部LBS）取。
//                    		      stepA1:更新定位请求次数(流控)
								dbh.addCmsUserReqCount(cmsUser);
//								stepA2:安徽联通号码校验
								if(("spOne").equals(cmsUser.getLogin_name())){
									isUnicomPhone = true;
								}else{
									isUnicomPhone = dbh.isUnicomPhoneSection(tel);
								}
								
								
								if(!isUnicomPhone){ // 非联通号段，禁止定位
									ans.getLia().setResult("127"); // 127:禁止定位 (用户查询的隐私鉴权未通过)
									respStr = respHead+xStream.toXML(ans);
									log.info("isUnicomPhone:"+isUnicomPhone+",reqIsLIRcode127,resp:"+respStr);
									return respStr;
								}
//							   stepB-0:黑白名单处理
								if(blackWhiteOpen){ //禁止定位 (用户查询的隐私鉴权未通过，在被查用户的黑名单或者被查用户禁止查询)
									boolean isBlackUser = this.checkIsBlackUser(tel);
									
									 if(isBlackUser){ // 如果是黑名单						   
											ans.getLia().setResult("127"); // 黑名单
											respStr = respHead+xStream.toXML(ans);
											log.info("isBlackUser,resp:"+respStr);
//											写定位历史
											Long tranc_time_end = System.currentTimeMillis();
											int tranc_times = (int) (tranc_time_end-tranc_time_start); //处理时间
											    entity = new TLbsHistory();
			                        		    entity.setUserId(cmsUser.getId());
			                        		     
			                        		    
			                        		    entity.setMdn(tel);
			                        		    entity.setJindu("");
			                        		    entity.setWeidu("");
			                        		    entity.setOrid(reqObject.getOriginator().getOrid());
											    entity.setRespCode(ans.getLia().getResult());
		
											    entity.setRespResult((byte)1);
											    respMemo = "黑名单号码";
											    entity.setRespMemo(respMemo);
											    entity.setServerCode(reqObject.getServiceid());
											    entity.setRespForm(respForm);
											    
											    entity.setReqTime(reqTime);
											    
											    entity.setTrancTimes(tranc_times);
											    
											    entity.setReqType(reqType);
			                        			int saveResult = saveLbsHistory(entity);
			                        			log.info("tel:"+tel+",saveHistory:"+saveResult); 
											return respStr;
									   }
									 boolean isWhiteUser = this.checkIsWhiteUser(tel,cmsUser.getId());
									   if(!isWhiteUser){ // 如果不在白名单
											ans.getLia().setResult("127"); // 不在白名单
											respStr = respHead+xStream.toXML(ans);
											log.info("isNotWhiteUser,resp:"+respStr);
//											写定位历史
											Long tranc_time_end = System.currentTimeMillis();
											int tranc_times = (int) (tranc_time_end-tranc_time_start); //处理时间
											    entity = new TLbsHistory();
			                        		    entity.setUserId(cmsUser.getId());			                        		    
			                        		    
			                        		    entity.setMdn(tel);
			                        		    entity.setJindu("");
			                        		    entity.setWeidu("");
			                        		    entity.setOrid(reqObject.getOriginator().getOrid());
											    entity.setRespCode(ans.getLia().getResult());
											     
											    entity.setRespResult((byte)1);
											    respMemo = "非白名单号码";
												entity.setRespMemo(respMemo);
												
											    entity.setServerCode(reqObject.getServiceid());
											    entity.setRespForm(respForm);
											    
											    entity.setReqTime(reqTime);
											    
											    entity.setTrancTimes(tranc_times);											    
											    entity.setReqType(reqType);
			                        			int saveResult = saveLbsHistory(entity);
			                        			log.info("tel:"+tel+",saveHistory:"+saveResult); 
											return respStr;
										   
									   }
								}
							  
								
								
								LIACacheManager liaCM = LIACacheManager.getInstance();
								ans = liaCM.getCacheByKey(userName+tel); // 取缓存数据
								if(null==ans){
//								stepB-1: 请求总部定位结果
									log.info("begin to access GLSC,key:"+tel);
									GLSCProxy glscP = new GLSCProxy();
									ans = glscP.reqFromLbscToGLSC((Req)reqObject.clone());
									respStr = respHead+xStream.toXML(ans);
//							    stepB-3:将请求结果写入缓存
									liaCM.putCache(userName+tel, ans);


								}else{
//									stepB-2: 用缓存定位结果
									respStr = respHead+xStream.toXML(ans);
									respForm = 1;
									log.info("key:"+tel+" hadInCache:"+ans);	
								}
//								stepB-4:将定位结果写入历史表
								Long tranc_time_end = System.currentTimeMillis();
								int tranc_times = (int) (tranc_time_end-tranc_time_start); //处理时间
								    entity = new TLbsHistory();
                        		    entity.setUserId(cmsUser.getId());
                        		    List<Posinfo> posinfos = ans.getLia().getPosinfos();
                        		    if(null!=posinfos&&posinfos.size()>0){
                        		    	entity.setJindu(posinfos.get(0).getLongitude());
                            		    entity.setWeidu(posinfos.get(0).getLatitude());
                        		    }else{
                        		    	entity.setJindu("");
                            		    entity.setWeidu("");
                            		    log.info("noJWTel:"+tel);
                        		    }
                        		    
                        		    entity.setMdn(tel);
                        		    
                        		    entity.setOrid(reqObject.getOriginator().getOrid());
								    entity.setRespCode(ans.getLia().getResult());
								    
								    if("0".equals(ans.getLia().getResult())){
								    	entity.setRespResult((byte)0);
								    	respMemo = "定位成功";
								    }else{
								    	entity.setRespResult((byte)1);
								    	respMemo = "pleaseWatchFile";
								    }
								    entity.setServerCode(reqObject.getServiceid());
								    entity.setRespForm(respForm);
								    
								    entity.setReqTime(reqTime);
								    
								    entity.setTrancTimes(tranc_times);
								    entity.setRespMemo(respMemo);
								    entity.setReqType(reqType);
                        			int saveResult = saveLbsHistory(entity);
                        			log.info("tel:"+tel+",saveHistory:"+saveResult); 
                        			return respStr;
							}
							
//					step3-3:多用户立即定位请求
						}else if(msidListSize>1){
//							注释以下三行，第四行开始编写对批量定位的处理
//							ans.getLia().setResult("126"); // 不支持的服务
//							respStr = respHead+xStream.toXML(ans);
//							log.info("reqIsMutiLIR126,resp:"+respStr);
//							批量定位处理startByBath to GLSC...
//							log.info("begin to testAccess GLSCBatch,key:"+tel);
//							GLSCProxy glscP = new GLSCProxy();
//							ans = glscP.reqFromLbscToGLSCBatch(reqObject);
//							respStr = respHead+xStream.toXML(ans);
//							log.info("begin to testAccess GLSCBatch,respStr:"+respStr);
							
//							批量定位处理start...single to GLSC
							
							Req oneReq = null;    // 新单次请求对象
							String oneTel = null; // 单个定位号码
							Ans oneAns = null;    // 单个响应对象
							Lir oneLir = null;    // 单个Lir对象
							Msids oneMsids = null; // 单个号码组对象
							List<String> oneMsid = null; // 用来设置一个号码
							GLSCProxy glscP = new GLSCProxy();
//							响应类型的定义：
							Lia batchLia = new Lia();
							List <Posinfo> posinfo = new ArrayList<Posinfo>();
							Posinfo onePosInfo = null;
//							缓存管理器
							LIACacheManager liaCM = LIACacheManager.getInstance();	
//							统计用的定位时间：
							Long tranc_time_startOne = null;
							Long tranc_time_endOne = null;
							int tranc_timesOne = 0;
							for(int k=0;k<msidListSize;k++){
								tranc_time_startOne = System.currentTimeMillis();
								oneTel = (String)msidList.get(k);
								log.info("inBatch:"+k+",key:"+oneTel);
//								step:流控和黑白名单检查start****************
								if(cmsUser==null||cmsUser.getReq_count()>=cmsUser.getReq_max()){ // 流控检查不能通过
									 Posinfo e = new Posinfo();
									 e.setMsid(oneTel);
									 e.setPositionresult("98");// 超过流控阀值(自定义)
									 posinfo.add(e);
                                     log.warn("reqIsLIRhadMax,mainKey:"+userName+oneTel);
									break;
								}else{// 流控检查通过，则继续：黑白名单处理,从缓存取定位结果，没有就从远程服务端（总部LBS）取。
									dbh.addCmsUserReqCount(cmsUser); // 更新流控信息 
//									stepA2:安徽联通号码校验
									isUnicomPhone = dbh.isUnicomPhoneSection(oneTel);
									if(!isUnicomPhone){ // 非联通号段，禁止定位
										 Posinfo e = new Posinfo();
										 e.setMsid(oneTel);
										 e.setPositionresult("127");// 127:禁止定位 (用户查询的隐私鉴权未通过)
										 posinfo.add(e);										
										log.info(oneTel+",isNotUnicomPhone,result127.");
										continue;
									}
//								   stepB-0:黑白名单处理
									if(blackWhiteOpen){ //禁止定位 (用户查询的隐私鉴权未通过，在被查用户的黑名单或者被查用户禁止查询)
										boolean isBlackUser = this.checkIsBlackUser(oneTel);
										
										 if(isBlackUser){ // 如果是黑名单
											 Posinfo e = new Posinfo();
											 e.setMsid(oneTel);
											 e.setPositionresult("99");// 黑名单(自定义)
											 posinfo.add(e);
											 log.warn("isBlackUserInBatch,mainKey:"+userName+oneTel+",posinfo:"+e);
//												stepX:将定位结果写入历史表
												tranc_time_endOne = System.currentTimeMillis();
												tranc_timesOne = (int) (tranc_time_endOne-tranc_time_startOne); //处理时间
												    
												    entity = new TLbsHistory();
				                        		    entity.setUserId(cmsUser.getId());
				                        		    entity.setMdn(oneTel);
				                        		    entity.setOrid(reqObject.getOriginator().getOrid());
												    entity.setRespCode(e.getPositionresult());
												    entity.setRespResult((byte)1);
												    respMemo = "黑名单号码";
												   
												    entity.setServerCode(reqObject.getServiceid());
												    entity.setRespForm(respForm);
												    
												    entity.setReqTime(reqTime);
												    
												    entity.setTrancTimes(tranc_timesOne);
												    entity.setRespMemo(respMemo);
												    entity.setReqType(reqType+"Bat");
				                        			int saveResult = saveLbsHistory(entity);
				                        			log.info("tel:"+tel+",saveHistory:"+saveResult);
											 continue;
										   }
										 boolean isWhiteUser = this.checkIsWhiteUser(oneTel,cmsUser.getId());
										   if(!isWhiteUser){ // 如果不在白名单
											   Posinfo e = new Posinfo();
												 e.setMsid(oneTel);
												 e.setPositionresult("97");// 不在白名单(自定义)
												 posinfo.add(e);
												log.info("isNotWhiteUser97,mainKey:"+userName+oneTel+",posinfo:"+e);
//												stepX:将定位结果写入历史表
												tranc_time_endOne = System.currentTimeMillis();
												tranc_timesOne = (int) (tranc_time_endOne-tranc_time_startOne); //处理时间
												    
												    entity = new TLbsHistory();
				                        		    entity.setUserId(cmsUser.getId());
				                        		    entity.setMdn(oneTel);
				                        		    entity.setOrid(reqObject.getOriginator().getOrid());
												    entity.setRespCode(e.getPositionresult());
                                                    entity.setRespResult((byte)1);
												    respMemo = "非白名单号码";
												    
												    entity.setServerCode(reqObject.getServiceid());
												    entity.setRespForm(respForm);
												    
												    entity.setReqTime(reqTime);
												    
												    entity.setTrancTimes(tranc_timesOne);
												    entity.setRespMemo(respMemo);
												    entity.setReqType(reqType+"Bat");
				                        			int saveResult = saveLbsHistory(entity);
				                        			log.info("tel:"+tel+",saveHistory:"+saveResult);
												continue;											   
										   }
									}
								
								}// end
								
//								流控和黑白名单检查end*****************
//								step3-3-1:构造单次请求体Req
								oneMsid = new ArrayList<String>(1);
								oneMsid.add(oneTel);
								
								oneReq = new Req();
//								新增修改：Originator
								Originator oneOriginator = reqObject.getOriginator();
								oneOriginator.setOrid(oneTel);
								
								oneReq.setOriginator(oneOriginator);
								oneReq.setReqPlatform(reqObject.getReqPlatform());
								oneReq.setServiceid(reqObject.getServiceid());
								oneReq.setClient(reqObject.getClient());
//								step3-3-1-A:构造Lir
								oneLir = new Lir();
							

								
								oneLir.setOriguserAccessType(lirOne.getOriguserAccessType());
								oneLir.setFindmeIndic(lirOne.getFindmeIndic());
//								step3-3-1-B:构造Msids
								oneMsids = new Msids();
								oneMsids.setMsidType(lirOne.getMsids().getMsidType());
								
								oneMsids.setMsid(oneMsid);
								
								oneLir.setMsids(oneMsids);
								
//								新增：LL_FORMAT
								GeoInfo geoInfo = new GeoInfo();
								geoInfo.setCoordSys("LL"); // 经度纬度格式
						        geoInfo.setDatum("WGS-84"); // 全球大地测量系统 1984
						        geoInfo.setLlFormat("D5");
								
						        oneLir.setGeoInfo(geoInfo);
						        oneLir.setPosreqtype(lirOne.getPosreqtype()); // 新增
								
								oneReq.setLir(oneLir);
								
								
//								step3-3-2:单次请求总部并获取响应,加上缓存机制：
								oneAns = liaCM.getCacheByKey(userName+oneTel); // 取缓存数据
								if(oneAns==null){ // 缓存中没有,则请求总部接口,将请求结果写入缓存
									oneAns = glscP.reqFromLbscToGLSC((Req)oneReq.clone());
									liaCM.putCache(userName+oneTel, oneAns);
									log.info("inBatchByGlsc:"+k+",key:"+oneTel+",responeAns:"+oneAns);
								}else{									
									respForm = 1;
									log.info("inBatchByCache:"+k+",key:"+oneTel+",responeAns:"+oneAns);
									
								}
								
//								step3-3-3:分析响应，组装到批量定位响应
								if(k==0){
									ans.setLcsclientid(oneAns.getLcsclientid());
									ans.setOrid(oneAns.getOrid());
									ans.setVer(oneAns.getVer());
									batchLia.setResult(oneAns.getLia().getResult());
								}
								onePosInfo = oneAns.getLia().getPosinfos().get(0);
								posinfo.add(onePosInfo);
//								step3-3-4:将定位结果写入历史表
								tranc_time_endOne = System.currentTimeMillis();
								tranc_timesOne = (int) (tranc_time_endOne-tranc_time_startOne); //处理时间
								    
								    entity = new TLbsHistory();
                        		    entity.setUserId(cmsUser.getId());
                        		   
                        		    
                        		    entity.setMdn(oneTel);
                        		    entity.setJindu(onePosInfo.getLongitude());
                        		    entity.setWeidu(onePosInfo.getLatitude());
                        		    entity.setOrid(reqObject.getOriginator().getOrid());
//                        		    旧版：
//								    entity.setRespCode(onePosInfo.getPositionresult());
//                        		    新版：
                        		    entity.setRespCode(oneAns.getLia().getResult());
                        		    
								    
								    if("1".equals(onePosInfo.getPositionresult())||"2".equals(onePosInfo.getPositionresult())
								    	||"3".equals(onePosInfo.getPositionresult())){
								    	entity.setRespResult((byte)0);
								    	respMemo = "定位成功";
								    }else{
								    	entity.setRespResult((byte)1);
								    	respMemo = "pleaseWatchDocfile";
								    }
								    entity.setServerCode(reqObject.getServiceid());
								    entity.setRespForm(respForm);
								    
								    entity.setReqTime(reqTime);
								    
								    entity.setTrancTimes(tranc_timesOne);
								    entity.setRespMemo(respMemo);
								    entity.setReqType(reqType+"Bat");
                        			int saveResult = saveLbsHistory(entity);
                        			log.info("tel:"+oneTel+",saveHistory:"+saveResult);
								    oneAns = null;
							} // end for 循环
							
							batchLia.setPosinfos(posinfo);
							ans.setLia(batchLia);
//							log.info("key:"+oneTel+"***HAHA***ans:"+ans);
							xStream.setMode(XStream.NO_REFERENCES);//不引用
							respStr = respHead+xStream.toXML(ans);
							
							
							log.info("inBatchkey:"+oneTel+",respStr:"+respStr);
//							批量定位处理end...							
//				    step3-4:请求数据异常：请求字符串不符合协议规则
						}else{
							ans.getLia().setResult("102"); // 被定位用户未知
							respStr = respHead+xStream.toXML(ans);
							log.info("reqIsLIR102,resp:"+respStr);
						}
					} // end else for step3-1.
					
//				【case:LTR】	
				}else if(reqType.equals("LTR")){
					boolean otherCheck = true;
//					生成REQ_ID
					int REQ_ID = MessageUtil.getSequenceId();
					
//					构造一个默认返回LTA的ANS
					ans = this.createDefaultAnsForLtr(reqObject,REQ_ID+"");

					Ltr ltr = reqObject.getLtr();
					List<String> msidList = ltr.getMsids().getMsid();
					if(msidList==null){
						ans.getLta().setResult("102"); // 被定位用户未知
						respStr = respHead+xStream.toXML(ans);
						log.info("reqIsLTRmsidListNUll102,resp:"+respStr);
						return respStr;
					}
//					
					int msidsCount = msidList.size();
					if(msidsCount!=1){ // 非单个用户，不能做周期定位
						ans.getLta().setResult("8"); // 位置请求的语法不对
						respStr = respHead+xStream.toXML(ans);
						log.info("reqIsLTRmsidSize>1,resp:"+respStr);
						return respStr;
					}
//					开始后续分析：
//					stepBB1:流控分析
					String tel = (String)msidList.get(0);
					DbHandle dbh = new DbHandle();
					CmsUser cmsUser =  dbh.queryCmsUserBySPipInfo(userName);
					if(cmsUser==null||cmsUser.getReq_count()>=cmsUser.getReq_max()){ // 流控检查不能通过
						
						ans.getLta().setResult("900"); // 900 : SP 请求达到流控最大值，拒绝定位请求.
						respStr = respHead+xStream.toXML(ans);
						log.info("reqIsLTRhadMax900,resp:"+respStr);
						return respStr;
						
					}
//                  流控检查通过，则继续分析
					dbh.addCmsUserReqCount(cmsUser); // 当天请求数+1 
//					stepA2:安徽联通号码校验
					isUnicomPhone = dbh.isUnicomPhoneSection(tel);
					if(!isUnicomPhone){ // 非联通号段，禁止定位
						ans.getLta().setResult("127"); // 127:禁止定位 (用户查询的隐私鉴权未通过)							
						respStr = respHead+xStream.toXML(ans);
						respMemo = "非联通号段，禁止定位";
						otherCheck = false;
						log.info(tel+",telisNotUniphone,resp:"+respStr);
					}
//					stepBB2:黑白名单分析
//					boolean blackWhiteOpen = cf.getBoolean("blackWhiteOpen", true); //黑白名单处理开关 // oldVersion
//					new Version 6 lines
					boolean blackWhiteOpen =  true;
					if(1==cmsUser.getCheckBw()){ // 不需要鉴权黑白名单
						blackWhiteOpen = false;
					}else{
						
					}
					if(blackWhiteOpen){
						boolean isBlackUser = this.checkIsBlackUser(tel);
						
						 if(isBlackUser){ // 如果是黑名单						   
								ans.getLta().setResult("127"); // 黑名单								
								respStr = respHead+xStream.toXML(ans);
								respMemo = "黑名单号码";
								otherCheck = false;
								log.info("isBlackUser,resp:"+respStr);
                                
						 }
						 boolean isWhiteUser = this.checkIsWhiteUser(tel,cmsUser.getId());
						 if(!isWhiteUser){ // 如果不在白名单
								ans.getLta().setResult("127"); // 不在白名单
								respStr = respHead+xStream.toXML(ans);
								respMemo = "非白名单号码";
								otherCheck = false;
								log.info("isNotWhiteUser,resp:"+respStr);							   
						 }
					} // 黑白名单分析结束...............................
//					stepBB3:周期性参数检查
					PrTimer  prTimer = ltr.getPrTimer();
					
					TimeRange timeRange = prTimer.getTimeRange();
					
					String startTime = timeRange.getStartTime();
					String stopTime = timeRange.getStopTime();
					String interval = timeRange.getInterval();
					
					long timeDifference_default =  cf.getLong("timeDifference_default"); // 秒单位的默认起止时间差
					long interval_default_min = cf.getLong("interval_default_min"); // 默认的定位周期间隔时间最小值（秒）
					long interval_default_max = cf.getLong("interval_default_max"); // 默认的定位周期间隔时间最大值（秒）
//                  临时变量
					int HH = 0;
					int mm = 0;
					int ss = 0;
					
					Date start_Date = null;
					Date stop_Date = null;
 
					long timeDifference = 0L;
					long interval_long = 0L;
					
					start_Date = DateUtil.parse(startTime);
					stop_Date = DateUtil.parse(stopTime);
					timeDifference = (stop_Date.getTime()-start_Date.getTime())/1000;
					
					
					HH = Integer.parseInt(interval.substring(0,2));
					mm = Integer.parseInt(interval.substring(2,4));
					ss = Integer.parseInt(interval.substring(4,6));
					
					interval_long = HH*60*60+mm*60+ss;
//					参数检验
					if(timeDifference<=0||timeDifference>timeDifference_default){
                         ans.getLta().setResult("7"); //请求中参数的格式不对
						 respStr = respHead+xStream.toXML(ans);
						 respMemo = "请求中周期参数非法，请求起止时间差:"+timeDifference;
						 otherCheck = false;
						 log.warn("notValidTimeDif:"+timeDifference+"s,timeDifference_default:"+timeDifference_default+"s,resp:"+respStr);
					}else{
						 if(interval_long<interval_default_min||interval_long>interval_default_max){							 
							 ans.getLta().setResult("7"); //请求中参数的格式不对
							 respStr = respHead+xStream.toXML(ans);
							 respMemo = "请求中周期参数非法，周期间隔为:"+interval_long+"秒";
							 otherCheck = false;
							 log.warn("notValidinterval_long:"+interval_long+"s,resp:"+respStr);							 
						 }
					}
					if(null==checkSPResult[1]||"".equals(checkSPResult[1])){
						 ans.getLta().setResult("7"); //请求中参数的格式不对
						 respStr = respHead+xStream.toXML(ans);
						 respMemo = "客户端没有填写定位报告接收reportURL";
						 otherCheck = false;
						 log.warn("notValidReportUrl:"+checkSPResult[1]+",resp:"+respStr);
					}
					if(!otherCheck){
						long tranc_time_end = System.currentTimeMillis();
						int tranc_time = (int) (tranc_time_end-tranc_time_start); //处理时间
						    
						    entity = new TLbsHistory();
                		    entity.setUserId(cmsUser.getId());
                		   
                		    
                		    entity.setMdn(tel);
                		    entity.setJindu("");
                		    entity.setWeidu("");
                		    entity.setOrid(reqObject.getOriginator().getOrid());
						    entity.setRespCode(ans.getLta().getResult());
						    
						    entity.setRespResult((byte)1);
						    
						    entity.setServerCode(reqObject.getServiceid());
						    entity.setRespForm(respForm);
						    
						    entity.setReqTime(reqTime);
						    
						    entity.setTrancTimes(tranc_time);
						    entity.setRespMemo(respMemo);
						    entity.setReqType(reqType);
                			int saveResult = saveLbsHistory(entity);
                			log.info("tel:"+tel+",saveHistory:"+saveResult);
                			respStr = respHead+xStream.toXML(ans);
                			return respStr;
					}
					
					
//					周期定位参数校验完毕，用quartz定时任务进行执行
					LirNeedEntity lirNEntity = new LirNeedEntity();
					
					lirNEntity.setReqId(REQ_ID);
					lirNEntity.setCmsUser(cmsUser);
					
					lirNEntity.setLcsclientid(userName);
					lirNEntity.setPassword(password);
					lirNEntity.setOrid(reqObject.getOriginator().getOrid());
					lirNEntity.setOridType(reqObject.getOriginator().getOridType());
					
					lirNEntity.setMsid(tel);
					lirNEntity.setMsidType(reqObject.getLtr().getMsids().getMsidType());
					lirNEntity.setServiceid(reqObject.getServiceid());
					lirNEntity.setReqPlatform(reqObject.getReqPlatform());
					
					lirNEntity.setPrio(reqObject.getLtr().getPrio());
					lirNEntity.setReqResultformat(reqObject.getLtr().getReqResultformat());
					lirNEntity.setSpReportUrl(checkSPResult[1]);
					
//					测试中，发现需要增加的参数 2013-09-03 03:32
					lirNEntity.setOriguserAccessType("3");
					lirNEntity.setFindmeIndic("0");
					lirNEntity.setPosreqtype("1");


					
					JobDetail job1 = this.createLtrrJobDetail(REQ_ID,lirNEntity);
					Trigger trigger1 = this.createASimpleTrigger(REQ_ID, start_Date, stop_Date, -1, interval_long);
					this.runJob(REQ_ID, job1, trigger1);
					
//					返回周期定位响应：LTA
					ans.getLta().setResult("0");
					respStr = respHead+xStream.toXML(ans);
					log.info("tel:"+tel+",reqIsLtr,respLtaIs:"+respStr);
					return respStr;
					
//				【case:LCTR】	
				}else if(reqType.equals("LCTR")){
					Lctr obj = reqObject.getLctr();
					boolean cancelOk = CancelLTRJob.cancelLtrWork(obj.getReqId());
					ans = this.createDefaultAnsForLctr(reqObject);// 构建默认的返回ANS：
					if(cancelOk){
						ans.getLcta().setResult("0");
					}else{

					}
					respStr = respHead+xStream.toXML(ans);
					log.info("reqIsLCTR,resp:"+respStr);
//				【case:非协议规定的请求】	
				}else{
					ans = createDefaultSingleRespWithLia(reqObject);// 构建默认的返回ANS：
					ans.getLia().setResult("126"); // 不支持的服务
					respStr = respHead+xStream.toXML(ans);
					log.info("reqIsUnknow126,resp:"+respStr);
					return respStr;
				}
//			step1-2:SP鉴权失败
			}else{ // 
				ans = createDefaultSingleRespWithLia(reqObject);// 构建默认的返回ANS：
				ans.getLia().setResult("103"); // LCS Client未授权或者密码不符
				respStr = respHead+xStream.toXML(ans);
				log.info("checkSPFail103,resp:"+respStr);
				return respStr;
			}

		}catch(Exception ex){
			//默认result:129(请求定位平台错误)
			respStr = respHead+xStream.toXML(ans);
			log.info("phraseExceptionDefaultResp:"+respStr);
			log.error("dealWithReqErrIs:",ex);
		}
		
		return respStr;
	}
	
	/**
	 * 
	* package_name: cn.gz.lbs.main
	* file_name:    SPRequestManager.java
	* description: 根据转换后的请求对象，创建默认的返回对象Ans
	*              默认result:129(请求定位平台错误)
	* 2013-7-9上午10:14:29
	* Author: chenhui
	 * @param reqObject
	 * @return 
	 */
	private Ans  createDefaultSingleRespWithLia(Req reqObject){
		
		Ans ans = null;
		try{
			String lcsClientId = reqObject.getClient().getLcsclientid();
			String orid = reqObject.getOriginator().getOrid();
//			构建ANS
			ans = new Ans();
			ans.setLcsclientid(lcsClientId);
			ans.setOrid(orid);
			
//			构建lia对象。
			Lia lia = new Lia();
			lia.setResult("129");
			
			List <Posinfo> posinfos = new ArrayList<Posinfo>();
			Posinfo e = new Posinfo();
			e.setPositionresult("20");
			posinfos.add(e);
			lia.setPosinfos(posinfos);
			ans.setLia(lia);
			
		}catch(Exception ex){
			ans = null;
			ex.printStackTrace();
			log.warn("createDefaultRespError:",ex);
		}
		
		log.info("defaultAns:"+ans);
		return ans;
		
	}
	
	/**
	 * 
	* package_name: cn.gz.lbs.main
	* file_name:    SPRequestManager.java
	* description: 构造默认的周期定位响应
	* 2013-8-15下午6:03:26
	* Author: chenhui
	 * @param reqObject
	 * @return
	 */
	private Ans  createDefaultAnsForLtr(Req reqObject,String reqId){
		
		Ans ans = null;
		try{
			String lcsClientId = reqObject.getClient().getLcsclientid();
			String orid = reqObject.getOriginator().getOrid();
//			构建ANS
			ans = new Ans();
			ans.setLcsclientid(lcsClientId);
			ans.setOrid(orid);
			
//			构建LTA对象。
			Lta lta = new Lta();
			lta.setReqId(reqId);
//			MIDS构造start...
			Msids msids = new Msids();
			List<String> msid = new ArrayList<String>();
			msid.add(orid);			 
			msids.setMsid(msid);			
			msids.setMsidType("0");
//			MIDS构造end...
			lta.setResult("129");
           
			ans.setLta(lta);
			
		}catch(Exception ex){
			ans = null;
			ex.printStackTrace();
			log.warn("createDefaultLTARespError:",ex);
		}
		
		log.info("defaultLTAAns:"+ans);
		return ans;
		
	}


	/**
	 * 
	* package_name: cn.gz.lbs.main
	* file_name:    SPRequestManager.java
	* description: 构建默认的Lcta 取消周期定位响应的Ans
	* 2013-9-3上午12:39:13
	* Author: chenhui
	 * @param reqObject
	 * @return
	 */
	private Ans  createDefaultAnsForLctr(Req reqObject){
		
		Ans ans = null;
		try{
			String lcsClientId = reqObject.getClient().getLcsclientid();
//			构建ANS
			ans = new Ans();
			ans.setLcsclientid(lcsClientId);
			
//			构建lia对象。
			Lcta lcta = new Lcta();
			lcta.setReqId(reqObject.getLctr().getReqId());
			lcta.setResult("1"); // 0 表示成功. 
			ans.setLcta(lcta);
			
		}catch(Exception ex){
			ans = null;
			ex.printStackTrace();
			log.warn("createDefaultLctaRespError:",ex);
		}
		
		log.info("defaultLctaAns:"+ans);
		return ans;
		
	}
	
	
	/**
	 * 
	* package_name: cn.gz.lbs.main
	* file_name:    SPRequestManager.java
	* description: SP鉴权
	* 2013-6-20上午3:24:37
	* Author: chenhui
	 * @param ip
	 * @param user
	 * @param pwd
	 * @return checkSPResult[]  第一个元素：为字符串true表示鉴权通过；第二个元素为reportUrl。
	 */
	private static String[] checkSP(String ip,String user,String pwd){
		String checkSPResult[] = {"false",null};
		try{
			DbHandle dbh = new DbHandle();
			checkSPResult = dbh.isSafeIp(ip, user, pwd);
		}catch(Exception ex){
			ex.printStackTrace();
		}
		return checkSPResult;
	}
	
	/**
	 * 
	* package_name: cn.gz.lbs.main
	* file_name:    SPRequestManager.java
	* description: 判断请求的定位类型
	* 2013-7-8下午11:11:44
	* Author: chenhui
	 * @param req
	 * @return
	 */
	private  String checkReqType(String req){
		String type = null;
		try{
			if(req.toUpperCase().contains("LIR")){
				type = "LIR";
			}else if(req.toUpperCase().contains("LTR")){
				type = "LTR";
			}else if(req.toUpperCase().contains("LCTR")){
				type = "LCTR";
			}else{
				
			}
			
		}catch(Exception ex){
			log.error("checkReqTypeErrorIs:",ex);
		}
		return type;
	}
	
	
	/**
	 * 
	* package_name: cn.gz.lbs.main
	* file_name:    SPRequestManager.java
	* description: 调用数据库操作类，写定位记录到定位历史表
	* 2013-7-9下午3:56:19
	* Author: chenhui
	 * @param entity
	 * @return
	 */
	private int saveLbsHistory(TLbsHistory entity){
		int savaResult = 99;
		try{
			DbHandle dbh = new DbHandle();
			savaResult= dbh.saveLbsHistory(entity);

		}catch(Exception ex){
			log.error("errorWhenCallSaveHistory:",ex);
		}
		return savaResult;
	}
	
	/**
	 * 
	* package_name: cn.gz.lbs.main
	* file_name:    SPRequestManager.java
	* description: 白名单检查 
	* 2013-7-19下午5:11:11
	* Author: chenhui
	 * @param mdn
	 * @return
	 */
	private boolean checkIsWhiteUser(String mdn,long userId){
		boolean isWhite = true;
		try{
			DbHandle dbh = new DbHandle();
			isWhite = dbh.checkIsWhite(mdn,userId);
		}catch(Exception ex){
			ex.printStackTrace();
		}
		return isWhite;
	}
	
	/**
	 * 
	* package_name: cn.gz.lbs.main
	* file_name:    SPRequestManager.java
	* description: 黑名单检查
	* 2013-7-19下午5:10:57
	* Author: chenhui
	 * @param mdn
	 * @return
	 */
	private boolean checkIsBlackUser(String mdn){
		boolean IsBlack = false;
		try{
			DbHandle dbh = new DbHandle();
			IsBlack = dbh.checkIsBlack(mdn);
		}catch(Exception ex){
			ex.printStackTrace();
		}
		return IsBlack;
	}
	
	
	/**
	 * 
	* package_name: cn.gz.lbs.main
	* file_name:    SPRequestManager.java
	* description: 创建【周期定位转变成单次定位定时任务，以及负责返回给SP定位周期报告JOB】
	*              Create a JobDetail with the given name, and group
	*              name:  "job"+reqId 
	*              group: "jobGroup"+reqId
	* 2013-8-30下午1:53:12
	* Author: chenhui
	 * @param jobName
	 * @return
	 */
	public JobDetail createLtrrJobDetail(int reqId,LirNeedEntity entity){
		JobDetail job = null;
		try{
			job = new JobDetail("job"+reqId, "jobGroup"+reqId, LtrrJob.class);
			job.getJobDataMap().put("entity", entity);
		}catch(Exception ex){
			ex.printStackTrace();
			log.error("ctJobError:",ex);
		}
		return job;
	}
	
	/**
	 * 
	* package_name: cn.gz.lbs.main
	* file_name:    SPRequestManager.java
	* description: 根据传入参数，创建一个触发器
	*              triggerName: "trigger"+reqId 
	*              triggerGroup: "triggerGroup"+reqId
	* 2013-8-30下午1:58:43
	* Author: chenhui
	 * @param reqId 报告ID int
	 * @param startTime 任务开始时间 Date
	 * @param endTime   任务结束时间 Date
	 * @param repeatCount int [默认 -1 ，不限次数]
	 * @param interval long 每次定位任务执行间隔时间 (秒)
	 * @return SimpleTrigger
	 */
	public SimpleTrigger createASimpleTrigger(int reqId, Date startTime,
			Date endTime, int repeatCount, long interval){
		
		SimpleTrigger st = null;
		try{		
			long repeatInterval = interval*1000; // 单位是毫秒
			
			st =  new SimpleTrigger("trigger"+reqId,"triggerGroup"+reqId,startTime,
					endTime,repeatCount,repeatInterval);
		}catch(Exception ex){
			log.error("ctTriggerError:",ex);
		}
		return st;
	}
	

	/**
	 * 
	* package_name: cn.gz.lbs.main
	* file_name:    SPRequestManager.java
	* description: 根据传入的job和trigger，调度任务执行启动。
	*              调度器名称："scheduler"+reqId
	* 2013-8-30下午2:44:55
	* Author: chenhui
	 * @param reqId 定位报告ID
	 * @param job
	 * @param trigger
	 */
	public void runJob(int reqId,JobDetail job,Trigger trigger){
		
		try{ 
			StdSchedulerFactory sf = new StdSchedulerFactory();

			Properties props = new Properties();

			props.put("org.quartz.scheduler.instanceName","scheduler"+reqId);
			props.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
			props.put("org.quartz.threadPool.threadCount", "2");
			
//			props.put("org.quartz.threadPool.threadPriority", "5");
//			props.put("org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread", "true");

			sf.initialize(props);

			Scheduler scheduler1 = sf.getScheduler();

            scheduler1.scheduleJob(job, trigger);
            scheduler1.start();
            log.info("jobName"+job.getName()+",schedulerName:"+scheduler1.getSchedulerName()+",beginToStart.");
            
		}catch(Exception ex){
			ex.printStackTrace();
			log.error("runJobError:",ex);
		}
		
	}

	
//	end class.
}
